package org.offsync.async

import org.offsync.util.Window
import org.offsync.rich._

trait AsyncInputStream {
  private val readWindow = new Window[Byte](8) 
  
  def readSome(window: Window[Byte])(task: (() => Int) => Unit): Unit

  def readFully(window: Window[Byte])(task: (() => Int) => Unit): Unit
  
  def readShort = new (((() => Short) => Unit) => Unit) {
    def apply(readShortCompletion: (() => Short) => Unit): Unit = {
      val intWindow = readWindow.until(2)
      readFully(intWindow) { readCompletion =>
        val bytesread = try {
          readCompletion()
        } catch {
          case e => {
            readShortCompletion { () => throw e.wrap() }
            return
          }
        }
        
        readShortCompletion { () =>
          val result =
            (intWindow(2).asInstanceOf[Short] << 8) +
            (intWindow(3).asInstanceOf[Short] << 0)
          result.asInstanceOf[Short]
        }
      }
    }
  }
  
  def readInt = new (((() => Int) => Unit) => Unit) {
    def apply(readIntCompletion: (() => Int) => Unit): Unit = {
      val intWindow = readWindow.until(4)
      readFully(intWindow) { readCompletion =>
        val bytesread = try {
          readCompletion()
        } catch {
          case e => {
            readIntCompletion { () => throw e.wrap() }
            return
          }
        }
        
        readIntCompletion { () =>
          (intWindow(0).asInstanceOf[Int] << 24) +
          (intWindow(1).asInstanceOf[Int] << 16) +
          (intWindow(2).asInstanceOf[Int] << 8) +
          (intWindow(3).asInstanceOf[Int] << 0)
        }
      }
    }
  }
  
  def readLong = new (((() => Long) => Unit) => Unit) {
    def apply(readLongCompletion: (() => Long) => Unit): Unit = {
      val intWindow = readWindow.until(8)
      readFully(intWindow) { readCompletion =>
        val bytesread = try {
          readCompletion()
        } catch {
          case e => {
            readLongCompletion { () => throw e.wrap() }
            return
          }
        }
        
        readLongCompletion { () =>
          (intWindow(0).asInstanceOf[Long] << 56) +
          (intWindow(1).asInstanceOf[Long] << 48) +
          (intWindow(2).asInstanceOf[Long] << 40) +
          (intWindow(3).asInstanceOf[Long] << 32) +
          (intWindow(4).asInstanceOf[Long] << 24) +
          (intWindow(5).asInstanceOf[Long] << 16) +
          (intWindow(6).asInstanceOf[Long] << 8) +
          (intWindow(7).asInstanceOf[Long] << 0)
        }
      }
    }
  }
}
